<template>
  <div class="category-template" v-loading="optionLoading || initRender">
    <div class="change-setting" @click="changeSettingExpand">
      <el-tooltip effect="dark" :content="`点击${expandSetting ? '收起' : '展开'}设置栏`" placement="bottom">
        <div class="change-setting-wrap">
          <el-icon :class="{ 'rotate-icon': !expandSetting }"><ArrowDown /></el-icon>
        </div>
      </el-tooltip>
    </div>
    <div class="setting-header" :style="{ top: expandSetting ? '0px' : '-60px', 'box-shadow': expandSetting ? '0 0 18px rgba(0, 0, 0, 0.2)' : 'none' }">
      <div class="setting-header-left">
        <span class="logo">
          <el-icon><Monitor /></el-icon>
          <span class="logo-text">
            <span class="primary">集约化平台</span>
          </span>
        </span>
      </div>
      <div class="setting-header-center">
        
      </div>
      <div class="setting-header-right">
        <button class="option-btn active" @click="handleSave">
          <el-icon><FolderChecked /></el-icon>
          保存
        </button>
      </div>
    </div>
    <!-- 预览编辑页面 -->
    <div class="setting-web" :style="{ 'padding-top': expandSetting ? '60px' : '0px' }">
      <div class="setting-web-preview">
        <!-- PC预览 -->
        <div class="setting-web-preview-pc">
          <div v-if="webConfig.isShowLayout && headConfig.componentList?.length > 0" class="setting-web-head" @click.prevent="handleWebClick">
            <ComponentRender v-for="(item, index) in headConfig.componentList" :key="index" :element="item" :index="index" :showToolBar="false" />
          </div>
          <draggable
            v-if="webList.length > 0"
            class="setting-web-body" 
            v-model="webList" 
            animation="150" 
            group="component" 
            item-key="componentKey"
          >
            <template #item="{element, index}">
              <ComponentRender v-if="renderedList.includes(index)" :element="element" :index="index" @nextRender="nextRender" @mouseEvent="mouseEvent" :initRender="initRender" />
            </template>
          </draggable>
          <div v-if="webConfig.isShowLayout && footConfig.componentList?.length > 0" class="setting-web-foot" @click.prevent="handleWebClick">
            <ComponentRender v-for="(item, index) in footConfig.componentList" :key="index" :element="item" :index="index" :showToolBar="false" />
          </div>
        </div>
      </div>
    </div>
    <!-- 组件配置表单 -->
    <ConfigPanel />
    <!-- 添加选择器面板 -->
    <div
      v-show="showSelectorPanel"
      class="editor-selector-panel"
      :style="{
        left: selectorPosition.x + 'px',
        top: selectorPosition.y + 'px'
      }"
    >
      <div
        v-for="(editor, index) in overlappingEditors"
        :key="editor.getAttribute('_key')"
        class="editor-selector-item"
        @click="handleEditorSelect(editor)"
        @mouseenter="handleSelectorItemHover(editor)"
        @mouseleave="handleSelectorItemLeave(editor)"
      >
        <el-icon class="iconfont" :title="index === 0 ? '当前元素' : `上级元素${index}`"><EditPen /></el-icon>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, watch, computed, provide, onBeforeUnmount, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex'
import { checkPreview, insertTemplate, continueUpdate, updateTemplate, selectTemplateById } from '@/api/template'
import { updateSite } from '@/api/site'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ArrowDown, Monitor, FolderChecked, EditPen } from '@element-plus/icons-vue'
import { generateCustomString, generateColorGradient } from '@/utils/tools'
import draggable from 'vuedraggable'
import ConfigPanel from './components/ConfigPanel.vue'
import ComponentRender from './components/ComponentRender.vue'

const currentIndex = ref(0)
const renderedList = ref([0])
const initRender = ref(false)
const nextRender = async () => {
  currentIndex.value += 1
  if (currentIndex.value < webList.value.length) {
    renderedList.value.push(currentIndex.value)
  } else {
    initRender.value = false
  }
}
const router = useRouter()
const store = useStore()
const siteId = computed(() => store.state.site.currentSite?.id)
const catId = computed(() => {
  if (router.currentRoute.value.query.catId) {
    return Number(router.currentRoute.value.query.catId)
  }
  return null
})
const templateId = computed(() => {
  if (router.currentRoute.value.query.id) {
    return Number(router.currentRoute.value.query.id)
  }
  return null
})
const templateType = computed(() => {
  if (router.currentRoute.value.query.templateType) {
    return Number(router.currentRoute.value.query.templateType)
  }
  return null
})

// 当前栏目
const categoryDetail = computed(() => store.state.category.categoryFlat.find(item => item.id == router.currentRoute.value.query.catId))
// 收起、展开顶部设置栏
const expandSetting = ref(true)
const changeSettingExpand = () => {
  expandSetting.value = !expandSetting.value
}
/*****************************************样式修改start**********************************/
// --ruifox-color-primary-1
const defaultThemeColor = ref('')
const themeColor = ref('')
const changeTheme = value => {
  if (!value) return
  themeColor.value = value
  document.documentElement.style.setProperty('--theme-color', value)
  const gradient = generateColorGradient(value)
  // 根据返回的数组，按顺序分别设置css变量ruifox-color-primary-1到ruifox-color-primary-6
  for (let i = 1; i <= 6; i++) {
    document.documentElement.style.setProperty(`--ruifox-color-primary-${i}`, gradient[i - 1])
  }
}

watch(categoryDetail, newVal => {
  if (newVal) {
    themeColor.value = newVal.info?.themeColor || store.state.site.currentSite?.themeColor
    defaultThemeColor.value = themeColor.value
    changeTheme(defaultThemeColor.value)
  }
}, { deep: true, once: true })
/*****************************************样式修改end**********************************/
/*****************************************组件添加start**********************************/
// 编辑区域相关逻辑
const webList = ref([]) // 编辑区元素列表
const webConfig = ref({
  content: {},
  isShowLayout: true
}) // 编辑区元素配置(包括所有组件变量)
watch(
  webList,
  () => {
    store.commit('template/SET_COMPONENT_LIST', webList.value)
    store.commit('template/SET_CATEGORY_VARIABLE', webConfig.value.content)
    console.log(webList.value, 66666666)
  },
  { deep: true }
)

// 工具栏绑定鼠标事件（只选择 setting-web-body 下的组件）
const selectedEditor = ref(null)
const mouseEvent = () => {
  const components = document.querySelector('.setting-web-body')?.querySelectorAll('.setting-web-component:not([data-processed])')
  if (!components) return
  
  components.forEach(component => {
    component.setAttribute('data-processed', 'true')
    const editorElements = component.querySelectorAll('.ruifox-editor')
    editorElements.forEach(editor => {
      // 添加点击事件处理
      editor.addEventListener('click', event => {
        event.preventDefault()
        event.stopPropagation()
        // 获取当前元素的父级元素
        const elements = document.elementsFromPoint(event.clientX, event.clientY)
        const editors = elements.filter(el => el.classList.contains('ruifox-editor'))
        overlappingEditors.value = editors
        handleEditorSelect(editor)
        updateSelectorPosition()
      })

      editor.addEventListener('mouseenter', event => {
        // 阻止事件冒泡，避免触发父级editor的mouseenter
        event.stopPropagation()
        const elements = document.elementsFromPoint(event.clientX, event.clientY)
        const editors = elements.filter(el => el.classList.contains('ruifox-editor'))
        editors.forEach(item => handleSelectorItemLeave(item))
        handleSelectorItemHover(editor)
      })

      editor.addEventListener('mouseleave', event => {
        // 阻止事件冒泡，避免触发父级editor的mouseleave
        event.stopPropagation()
        handleSelectorItemLeave(editor)

        const toElement = event.relatedTarget
        if (!toElement?.closest('.editor-selector-panel')) {
          // 如果移动到了其他编辑器元素，触发该元素的mouseenter事件
          if (toElement?.closest('.ruifox-editor')) {
            const newEditor = toElement.closest('.ruifox-editor')
            const enterEvent = new MouseEvent('mouseenter', {
              bubbles: true,
              cancelable: true,
              clientX: event.clientX,
              clientY: event.clientY
            })
            newEditor.dispatchEvent(enterEvent)
          }
        }
      })
    })
  })
}

// 栏目组件列表处理
const flatComponentList = dataArray => {
  let result = []
  dataArray.forEach(item => {
    const { id, isShow, index, name, macro, componentKey, parentComponentKey, isCustom } = item
    const newItem = { id, isShow, index, name, macro, componentKey, parentComponentKey, isCustom }
    result.push(newItem)
    if (item.children && item.children.length > 0) {
      result = result.concat(flatComponentList(item.children))
    }
  })
  return result
}

// 组件更新(通过componentKey递归找到组件，更新其content)
const updateComponent = async (id, key, variableMap) => {
  let res
  try {
    res = await checkPreview({ id, variableMap, siteId: siteId.value, catId: catId.value })
  } catch {
    ElMessage.error('渲染代码失败，请联系管理员')
    return
  }
  if (res.code === 20000) {
    await loadResource(res.data)
    webConfig.value.content[key] = variableMap
    const component = findComponentByKey(webList.value, key)
    if (component) {
      component.content = res.data.content
    }
  }
}

const findComponentByKey = (list, key) => {
  function find(node) {
    if (node.componentKey === key) {
      return node
    }
    if (node.children) {
      for (let child of node.children) {
        const result = find(child)
        if (result) {
          return result
        }
      }
    }
    return null
  }
  for (let node of list) {
    const result = find(node)
    if (result) {
      return result
    }
  }
  return null
}
// 组件引用资源挂载
const loadResource = async data => {
  const { cssLinks = [], content = '' } = data

  try {
    // 1. 解析内联脚本和样式
    const parser = new DOMParser()
    const doc = parser.parseFromString(content, 'text/html')
    Array.from(doc.getElementsByTagName('link')).forEach(link => {
      if (!document.querySelector(`link[href="${link.href}"]`)) {
        document.head.appendChild(link.cloneNode(true))
      }
    })

    // 2. 加载CSS (不阻塞JS)
    cssLinks.forEach(item => {
      if (!document.querySelector(`link[href="${item.path}"]`)) {
        const link = document.createElement('link')
        link.rel = 'stylesheet'
        link.href = item.path
        document.head.appendChild(link)
      }
    })

  } catch (error) {
    ElMessage.error('css资源加载失败')
  }
}
// 自定义模板配置变量
const overlappingEditors = ref([]) // 存储重叠的编辑器元素
const showSelectorPanel = ref(false) // 控制选择器面板显示
const selectorPosition = reactive({
  // 选择器面板位置
  x: 0,
  y: 0
})

// 更新选择器面板位置的方法
const updateSelectorPosition = () => {
  // 没有选中元素，不显示
  if (!selectedEditor.value) return

  // 获取编辑器元素的位置信息
  const editorRect = selectedEditor.value.getBoundingClientRect()

  // 如果元素完全不在视口内，或者为移动端、最外层元素时，隐藏选择器面板
  if (editorRect.bottom < 0 || editorRect.top > window.innerHeight || 
    editorRect.right < 0 || editorRect.left > window.innerWidth || overlappingEditors.value.length === 1 || overlappingEditors.value[overlappingEditors.value.length - 1] === selectedEditor.value) {
    showSelectorPanel.value = false
    return
  } else {
    showSelectorPanel.value = true
  }

  // 获取视窗尺寸
  const viewportWidth = window.innerWidth

  // 计算面板尺寸
  const panelWidth = 40 // 修改为固定宽度40px
  const panelHeight = overlappingEditors.value.length * 34 // 每个选项34px高(包含padding)

  // 初始位置(元素右边缘)
  let x = editorRect.right
  let y = editorRect.top

  // 检查是否与toolbar重叠
  const toolbar = selectedEditor.value.closest('.setting-web-component')?.querySelector('.toolbar')
  if (toolbar) {
    const toolbarRect = toolbar.getBoundingClientRect()
    // 检查y轴和x轴是否都与toolbar重叠
    if (y >= toolbarRect.top && y <= toolbarRect.bottom) {
      // 检查x轴是否重叠
      const willOverlapToolbar = (x <= toolbarRect.right && x + panelWidth >= toolbarRect.left) || (x >= toolbarRect.left && x <= toolbarRect.right)
      if (willOverlapToolbar) {
        y += 30 // toolbar高度30px
      }
    }
  }

  // 如果面板会超出右边界或刚好在右边界，则显示在元素右内侧
  if (x + panelWidth >= viewportWidth || x === viewportWidth) {
    x = editorRect.right - panelWidth - 2 // 2px作为内侧边距
  }

  // 如果面板超出底部边界，向上调整位置
  if (y + panelHeight > window.innerHeight) {
    y = window.innerHeight - panelHeight - 5 // 底部预留5px间距
  }

  // 确保不会超出顶部
  y = Math.max(5, y) // 顶部预留5px间距
  selectorPosition.x = x
  selectorPosition.y = y
}

// 处理选择器面板中的选择
const curComponentId = ref('')
const handleEditorSelect = async editor => {
  let key = editor.getAttribute('_key')
  if (!key) {
    ElMessage.warning('当前元素未注明_key属性，请检查模板代码')
    return
  }
  // 向上查找最近的子组件包装器,获取子组件的配置对象
  let wrapper = editor.closest('.children-component')
  if (wrapper) {
    key = wrapper.getAttribute('data-props-key') + '.' + key
  }
  // 取editor的父级元素作为当前编辑的组件
  const editorDom = editor.closest('.setting-web-component')
  const componentKey = editorDom.getAttribute('data-component-key')
  const componentId = editorDom.getAttribute('data-component-id')
  // 如果组件id发生变化，则获取组件的默认变量
  if (componentId && componentId !== curComponentId.value) {
    curComponentId.value = componentId
    const res = await selectTemplateById({ id: componentId })
    store.commit('template/SET_COMPONENT_VARIABLE_DEFAULT', res.data.properties)
  }
  store.commit('template/SET_COMPONENT_VARIABLE', {id: componentId, key: componentKey})
  store.commit('template/SET_EDITOR_DOM', editorDom)
  store.commit('template/SET_EDITOR_VARIABLE', key)
  store.commit('template/SET_SHOW_CONFIG_PANEL', true)
  store.commit('template/SET_SHOW_TOOL_PANEL', false)
  // 清除旧的选中状态
  if (selectedEditor.value && selectedEditor.value !== editor) {
    selectedEditor.value.classList.remove('ruifox-editor-selected')
    handleSelectorItemLeave(selectedEditor.value)
  }
  // 设置选中元素
  editor.classList.add('ruifox-editor-selected')
  editor.style.outline = '1px dashed #409EFF'
  selectedEditor.value = editor
  updateSelectorPosition()
}

const handleSelectorItemHover = editor => {
  // 记录原始定位属性
  const originalPosition = window.getComputedStyle(editor).position
  // 添加遮罩
  editor.classList.add('ruifox-editor-hover-mask')
  editor.style.outline = '1px dashed #409EFF'
  // 如果有符合条件的原始定位，则使用原始定位
  if (['fixed', 'absolute'].includes(originalPosition)) {
    editor.style.position = originalPosition
  }
}

// 鼠标移出处理(已选中的不处理)
const handleSelectorItemLeave = editor => {
  if (!editor.classList.contains('ruifox-editor-selected')) {
    editor.style.outline = ''
    editor.classList.remove('ruifox-editor-hover-mask')
  }
}

// 阻止页面跳转
const handleWebClick = (e) => {
  if (e.target.tagName.toLowerCase() === 'a') {
    e.preventDefault()
  }
}
/*****************************************组件添加end**********************************/
/*****************************************编辑回显start********************************/
const _getCustomRender = async () => {
  optionLoading.value = true
  try {
    initRender.value = true
    const res = await continueUpdate({ templateId: templateId.value, catId: catId.value, siteId: siteId.value })
    if (res.code === 20000) {
      if (res.data.componentList.length === 0) {
        initRender.value = false
      }
      webList.value = await buildTree(res.data.componentList)
      webConfig.value.content = res.data.properties
      templateForm.value.name = res.data.name
      templateForm.value.macro = res.data.macro
    }
  } catch {
    initRender.value = false
  } finally {
    optionLoading.value = false
  }
}
const buildTree = async data => {
  const map = {}
  const roots = []

  // 首先构建 map
  data.forEach(item => {
    map[item.componentKey] = { ...item, children: [] }
  })

  // 使用 for...of 确保顺序以及加载完成
  for (const item of data) {
    await loadResource(item)

    if (item.parentComponentKey) {
      if (map[item.parentComponentKey]) {
        map[item.parentComponentKey].children.push(map[item.componentKey])
      }
    } else {
      roots.push(map[item.componentKey])
    }
  }

  return roots
}
/*****************************************编辑回显end**********************************/
// 站点头尾组件代码生成(变量取自身的properties)
const generateSiteTemplate = (dataForm, componentList, macro) => {
  const componentIds = new Set()
  let statements = []

  const recurse = list => {
    let innerStatements = []
    for (const item of list) {
      if (!item.isShow) return
      componentIds.add(item.id)
      if (item.children && item.children.length > 0) {
        let childrenStatements = recurse(item.children)
        let statement = `<#include fmTemplateManager.getPath(groupId, ${item.id}) /> \n <@${item.macro} properties.${item.componentKey} ${item.children.length}>${childrenStatements.join('')}</@${item.macro}>`
        innerStatements.push(statement)
      } else {
        let statement = `<#include fmTemplateManager.getPath(groupId, ${item.id}) /> \n <@${item.macro} properties.${item.componentKey} />`
        innerStatements.push(statement)
      }
    }
    return innerStatements
  }
  statements = recurse(componentList)
  statements = `<#macro ${macro} properties=variableMap> \n ${statements.join('\n')} \n </#macro>`
  dataForm.importIds = Array.from(componentIds)
  return statements
}

// 保存栏目模板
const templateForm = ref({
  name: '',
  content: '',
  type: 0,
  path: '',
  importIds: [],
  isBase: false
})
const optionLoading = ref(false)
const handleSave = async () => {
  // 如果当前主题色与默认主题色不同，则更新站点的主题色
  if (themeColor.value !== defaultThemeColor.value) {
    await updateSite({ id: siteId.value, themeColor: themeColor.value })
    await store.dispatch('site/updateSiteGroup')
  }
  if ([5, 6].includes(templateType.value)) {
    saveSiteTemplate(templateForm.value, webConfig.value.content, webList.value, templateType.value)
  }
}
// 站点头尾模板保存(分两种情况，一种是在站点下编辑，一种是栏目下编辑，两个有区别，所以需要靠传参来区分)
const saveSiteTemplate = (dataForm, properties, componentList, type) => {
  dataForm.componentList = JSON.stringify(flatComponentList(componentList))
  dataForm.properties = JSON.stringify(properties)
  dataForm.type = type
  let name
  if (type == 5) {
    name = dataForm.name ? dataForm.name : `头部模板`
    dataForm.macro = dataForm.macro ? dataForm.macro : generateCustomString('ruifox_head_siteId', siteId.value)
  } else {
    name = dataForm.name ? dataForm.name : `尾部模板`
    dataForm.macro = dataForm.macro ? dataForm.macro : generateCustomString('ruifox_foot_siteId', siteId.value)
  }
  dataForm.content = generateSiteTemplate(dataForm, componentList, dataForm.macro)
  ElMessageBox.prompt('请输入模板名称', '模板名称', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    inputPattern: /^[\u4e00-\u9fa5\w\s.,?!-]+$/,
    inputErrorMessage: '名称中不能包含特殊字符',
    inputValue: name
  })
    .then(async ({ value }) => {
      optionLoading.value = true
      dataForm.name = value
      let res
      if (dataForm.id) {
        res = await updateTemplate(dataForm)
      } else {
        res = await insertTemplate(dataForm)
      }
      if (res.code === 20000) {
        optionLoading.value = false
        ElMessage.success('操作成功，页面即将关闭')
        setTimeout(() => {
          window.close()
          window.opener.updatePage(type)
        }, 1000)
      }
    })
    .catch(() => {})
}

// 编辑器初始化(获取头尾组件)
const headConfig = reactive({ componentList: [] })
const footConfig = reactive({ componentList: [] })

// 加载公共头部资源
const loadCommonHeadResources = async () => {
  const head = document.head || document.getElementsByTagName('head')[0]
  const { commonResources } = store.state.base.groupSetting
  const basePath = process.env.NODE_ENV === 'development' ? commonResources.libPath_development : commonResources.libPath_production

  // 加载CSS
  commonResources.css.forEach(path => {
    const link = document.createElement('link')
    link.rel = 'stylesheet'
    link.href = basePath + path
    head.appendChild(link)
  })

  // 加载head中的JS
  const jsPromises = commonResources.headJs.map(path => {
    return new Promise((resolve) => {
      const script = document.createElement('script')
      script.src = basePath + path
      script.onload = resolve
      head.appendChild(script)
    })
  })
  await Promise.all([...jsPromises])
}

watch(() => store.state.base.groupSetting, async (newVal) => {
  if (!newVal.commonResources) return
  await loadCommonHeadResources()
  // 回显模板前，先获取模板的配置对象（内包含了所有引用组件的配置对象）
  // 如果是复用其他栏目的模板，那么通过templateId和自身catId在variable表里是找不到的，找不到就用默认属性
  if (templateId.value) {
    templateForm.value.id = templateId.value
    _getCustomRender()
  }
}, { immediate: true, deep: true })

provide('design', {
  updateComponent
})

onMounted(() => {
  const webPreview = document.querySelector('.setting-web')
  if (webPreview) {
    webPreview.addEventListener('scroll', () => {
      updateSelectorPosition()
    })
  }
})

onBeforeUnmount(() => {
  const webPreview = document.querySelector('.setting-web')
  if (webPreview) {
    webPreview.removeEventListener('scroll', updateSelectorPosition)
  }
})
</script>
<style lang="scss" scoped>
.category-template {
  height: 100vh;
  // 顶部展开收起wrap的按钮
  .change-setting {
    position: fixed;
    top: 0;
    left: 50%;
    margin-left: -53px;
    z-index: 2000;
    .change-setting-wrap {
      width: 106px;
      height: 16px;
      line-height: 16px;
      border-radius: 0 0 16px 16px;
      border: 1px solid #ebebf0;
      text-align: center;
      color: #787980;
      background-color: #f4f4f8;
      cursor: pointer;
      i {
        font-size: 14px;
        transform: rotate(180deg);
        transition: transform 0.3s ease-in-out;
      }
      .rotate-icon {
        transform: rotate(0deg);
      }
      &:hover {
        color: $white;
        background: #3f5dc7;
      }
    }
  }
  // 顶部wrap样式
  .setting-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1999;
    height: 60px;
    background-color: $white;
    display: flex;
    padding: 0 24px;
    justify-content: space-between;
    align-items: center;
    transition: all 0.3s;
    .setting-header-left {
      display: flex;
      align-items: center;
      .logo {
        display: flex;
        align-items: center;
        font-size: 18px;
        font-weight: 600;
        margin-right: 12px;
        cursor: default;
        user-select: none;
        
        i {
          font-size: 20px;
          margin-right: 10px;
          color: $mainColor;
        }

        .logo-text {
          display: flex;
          align-items: center;
          gap: 2px;
          
          .primary {
            color: $mainColor;
            font-weight: 700;
            text-shadow: 0 1px 2px rgba(63, 93, 199, 0.1);
          }
        }
      }
      .title {
        font-size: 14px;
        color: $black_2;
      }
      .name {
        width: 200px;
        font-size: 14px;
        color: $black_2;
        overflow: hidden;
        @include textEllipsis(14px, 1);
      }
      .line {
        margin: 0 10px;
        color: $black_2;
      }
    }
    .setting-header-center {
      position: absolute;
      left: 50%;
      bottom: 2px;
      transform: translateX(-50%);
      
      .device-preview {
        display: flex;
        align-items: center;
        padding: 6px;
        border-radius: 50%;
        color: $mainColor;
        cursor: pointer;
        
        &:hover {
          background-color: rgba(0, 0, 0, 0.1);
        }
        
        .iconfont {
          font-size: 24px;
        }
      }
    }
    .setting-header-right {
      display: flex;
      align-items: center;
      & > * {
        margin-left: 10px;
      }
      .option-btn {
        height: 32px;
        display: flex;
        justify-content: center;
        align-items: center;
        gap: 4px;
        padding: 0 12px;
        border: 1px solid $mainColor;
        border-radius: 4px;
        background-color: inherit;
        color: $mainColor;
        font-size: 14px;
        cursor: pointer;
        .iconfont {
          margin-right: 3px;
        }
      }
      .option-btn:hover {
        background-color: $mainColor;
        color: $white;
      }
      .option-btn.active {
        background-color: $mainColor;
        color: $white;
      }
    }
  }
  .setting-web {
    display: flex;
    justify-content: center;
    position: relative;
    padding-top: 60px;
    background: #fff;
    overflow: auto;
    transition: all 0.3s ease;

    .setting-web-preview {
      width: 100%;
      height: 100vh;
      transition: all 0.3s ease;
      
      .setting-web-preview-pc {
        width: 100%;
        height: 100%;
        border: 1px solid transparent;
      }
      
      .setting-web-preview-mobile {
        height: 100%;
        padding: 20px 0;
        border: 1px solid transparent;
        
        iframe {
          width: 100%;
          height: 100%;
          box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
          border-radius: 4px;
          transition: all 0.3s ease;
        }
      }

      &.mobile {
        width: 390px;
        margin: 0 auto;
      }
    }

    // 空状态样式
    .setting-web-body-empty {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 200px;
      background: #fff;
    }
  }
}

::v-deep .ruifox-editor-selected {
  outline: 1px dashed $mainColor !important;
}
::v-deep .el-tabs__nav {
  padding: 0 20px;
}

.editor-selector-panel {
  position: fixed;
  z-index: 1998;
  background: rgba(0, 0, 0, 0.7);
  border: none;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.editor-selector-item {
  padding: 8px 12px;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  border-bottom: 1px solid #fff;

  &:hover {
    background-color: rgba(255, 255, 255, 0.1);
  }

  .iconfont {
    font-size: 14px;
    color: #ffffff;
  }

  &.hover-highlight {
    background-color: rgba(255, 255, 255, 0.1);
  }
}

// 添加遮罩样式
::v-deep .ruifox-editor-hover-mask {
  position: relative;

  &::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(63, 93, 199, 0.1);
    pointer-events: none;
    z-index: 1999;
  }
}
</style>